package num

/*
import (
	"fmt"
	"math"
	"math/big"
	"strconv"
	"strings"
)

// NumberType represents the type of number
type NumberType int

const (
	INTEGER_TYPE NumberType = iota
	BIG_INTEGER_TYPE
	RATIONAL_TYPE
	REAL_TYPE
	COMPLEX_TYPE
)

// RNumber interface for basic number operations
type RNumber interface {
	Type() NumberType
	String() string
	RADD(RNumber) RNumber
	RSUB(RNumber) RNumber
	RMUL(RNumber) RNumber
	RDIV(RNumber) RNumber
	RNEG() RNumber
}

// Number interface for complex number operations
type Number interface {
	Type() NumberType
	String() string
	ADD(Number) Number
	SUB(Number) Number
	MUL(Number) Number
	DIV(Number) Number
	NEG() Number
}

// Integer represents an integer number
type Integer struct {
	Value int64
}

// Rational represents a rational number (numerator/denominator)
type Rational struct {
	Numerator   int64
	Denominator int64
}

// Real represents a real number
type Real struct {
	Value float64
}

// Complex represents a complex number with real and imaginary parts
type Complex struct {
	RealPart RNumber
	ImagPart RNumber
}

// Type returns the type of the integer
func (i Integer) Type() NumberType {
	return INTEGER_TYPE
}

// String returns the string representation of the integer
func (i Integer) String() string {
	return strconv.FormatInt(i.Value, 10)
}

// Type returns the type of the rational
func (r Rational) Type() NumberType {
	return RATIONAL_TYPE
}

// String returns the string representation of the rational
func (r Rational) String() string {
	return fmt.Sprintf("%d/%d", r.Numerator, r.Denominator)
}

// Type returns the type of the real
func (re Real) Type() NumberType {
	return REAL_TYPE
}

// String returns the string representation of the real
func (re Real) String() string {
	// Format with at least one decimal place to ensure 0.0 displays as "0.0"
	s := strconv.FormatFloat(re.Value, 'f', -1, 64)
	// If there's no decimal point, add ".0" to ensure it looks like a float
	if !strings.Contains(s, ".") {
		s += ".0"
	} else {
		// Remove trailing zeros but keep at least one decimal place
		s = strings.TrimRight(s, "0")
		if s[len(s)-1] == '.' {
			s += "0"
		}
	}
	return s
}

// Type returns the type of the complex
func (c Complex) Type() NumberType {
	return COMPLEX_TYPE
}

// String returns the string representation of the complex
func (c Complex) String() string {
	// Check if imaginary part is zero
	imagIsZero := false
	switch c.ImagPart.Type() {
	case INTEGER_TYPE:
		if c.ImagPart.(Integer).Value == 0 {
			imagIsZero = true
		}
	case REAL_TYPE:
		if c.ImagPart.(Real).Value == 0.0 {
			imagIsZero = true
		}
	default:
		// For other types, check if string representation is "0" or "0.0"
		imagStr := c.ImagPart.String()
		if imagStr == "0" || imagStr == "0.0" {
			imagIsZero = true
		}
	}

	if imagIsZero {
		return c.RealPart.String()
	}

	if c.RealPart.Type() == INTEGER_TYPE && c.RealPart.(Integer).Value == 0 {
		return fmt.Sprintf("%si", c.ImagPart.String())
	}

	// Check if imaginary part is negative to format correctly
	imagStr := c.ImagPart.String()
	if imagStr[0] == '-' {
		// If imaginary part is negative, remove the minus sign and use minus in the format
		imagStr = imagStr[1:]
		return fmt.Sprintf("%s-%si", c.RealPart.String(), imagStr)
	}

	return fmt.Sprintf("%s+%si", c.RealPart.String(), c.ImagPart.String())
}

// convertToNumber converts a Number to a CNumber
func convertToNumber(n RNumber) Number {
	switch n.Type() {
	case INTEGER_TYPE:
		return n.(Integer)
	case RATIONAL_TYPE:
		return n.(Rational)
	case REAL_TYPE:
		return n.(Real)
	default:
		return Complex{RealPart: n, ImagPart: Integer{Value: 0}}
	}
}

// isOne checks if a Number represents the value 1
func isOne(n RNumber) bool {
	switch n.Type() {
	case INTEGER_TYPE:
		return n.(Integer).Value == 1
	case RATIONAL_TYPE:
		r := n.(Rational)
		return r.Numerator == r.Denominator && r.Numerator != 0
	case REAL_TYPE:
		return n.(Real).Value == 1.0
	default:
		return false
	}
}

// ADD implements addition for Integer as a CNumber
func (i Integer) ADD(c Number) Number {
	return Complex{RealPart: i, ImagPart: Integer{Value: 0}}.ADD(c)
}

// SUB implements subtraction for Integer as a CNumber
func (i Integer) SUB(c Number) Number {
	return Complex{RealPart: i, ImagPart: Integer{Value: 0}}.SUB(c)
}

// MUL implements multiplication for Integer as a CNumber
func (i Integer) MUL(c Number) Number {
	return Complex{RealPart: i, ImagPart: Integer{Value: 0}}.MUL(c)
}

// DIV implements division for Integer as a CNumber
func (i Integer) DIV(c Number) Number {
	return Complex{RealPart: i, ImagPart: Integer{Value: 0}}.DIV(c)
}

// ADD implements addition for Rational as a CNumber
func (r Rational) ADD(c Number) Number {
	return Complex{RealPart: r, ImagPart: Integer{Value: 0}}.ADD(c)
}

// SUB implements subtraction for Rational as a CNumber
func (r Rational) SUB(c Number) Number {
	return Complex{RealPart: r, ImagPart: Integer{Value: 0}}.SUB(c)
}

// MUL implements multiplication for Rational as a CNumber
func (r Rational) MUL(c Number) Number {
	return Complex{RealPart: r, ImagPart: Integer{Value: 0}}.MUL(c)
}

// DIV implements division for Rational as a CNumber
func (r Rational) DIV(c Number) Number {
	return Complex{RealPart: r, ImagPart: Integer{Value: 0}}.DIV(c)
}

// ADD implements addition for Real as a CNumber
func (re Real) ADD(c Number) Number {
	return Complex{RealPart: re, ImagPart: Integer{Value: 0}}.ADD(c)
}

// SUB implements subtraction for Real as a CNumber
func (re Real) SUB(c Number) Number {
	return Complex{RealPart: re, ImagPart: Integer{Value: 0}}.SUB(c)
}

// MUL implements multiplication for Real as a CNumber
func (re Real) MUL(c Number) Number {
	return Complex{RealPart: re, ImagPart: Integer{Value: 0}}.MUL(c)
}

// DIV implements division for Real as a CNumber
func (re Real) DIV(c Number) Number {
	return Complex{RealPart: re, ImagPart: Integer{Value: 0}}.DIV(c)
}

// gcd calculates the greatest common divisor of two integers
func gcd(a, b int64) int64 {
	for b != 0 {
		a, b = b, a%b
	}
	return a
}

// simplifyRational simplifies a rational number by dividing numerator and denominator by their GCD
func simplifyRational(r Rational) RNumber {
	if r.Denominator == 0 {
		return r
	}

	// Handle negative denominators
	if r.Denominator < 0 {
		r.Numerator = -r.Numerator
		r.Denominator = -r.Denominator
	}

	// Find GCD
	d := gcd(int64(math.Abs(float64(r.Numerator))), r.Denominator)

	simplified := Rational{
		Numerator:   r.Numerator / d,
		Denominator: r.Denominator / d,
	}

	// If denominator is 1, return an integer
	if simplified.Denominator == 1 {
		return Integer{simplified.Numerator}
	}

	return simplified
}

// ConvertToSameType converts two numbers to the same (higher) type
func ConvertToSameType(a, b RNumber) (RNumber, RNumber) {
	typeA := a.Type()
	typeB := b.Type()

	// If both are the same type, no conversion needed
	if typeA == typeB {
		return a, b
	}

	// Determine the higher type
	higherType := typeA
	if typeB > typeA {
		higherType = typeB
	}

	var newA, newB RNumber

	// Convert a to higher type
	switch higherType {
	case RATIONAL_TYPE:
		if typeA == INTEGER_TYPE {
			newA = Rational{Numerator: a.(Integer).Value, Denominator: 1}
		} else {
			newA = a
		}

		if typeB == INTEGER_TYPE {
			newB = Rational{Numerator: b.(Integer).Value, Denominator: 1}
		} else {
			newB = b
		}

	case REAL_TYPE:
		switch typeA {
		case INTEGER_TYPE:
			newA = Real{Value: float64(a.(Integer).Value)}
		case RATIONAL_TYPE:
			r := a.(Rational)
			newA = Real{Value: float64(r.Numerator) / float64(r.Denominator)}
		default:
			newA = a
		}

		switch typeB {
		case INTEGER_TYPE:
			newB = Real{Value: float64(b.(Integer).Value)}
		case RATIONAL_TYPE:
			r := b.(Rational)
			newB = Real{Value: float64(r.Numerator) / float64(r.Denominator)}
		default:
			newB = b
		}
	}

	return newA, newB
}

// RADD implements addition for Integer
func (i Integer) RADD(n RNumber) RNumber {
	convertedI, convertedN := ConvertToSameType(i, n)

	switch convertedI.Type() {
	case INTEGER_TYPE:
		return Integer{Value: convertedI.(Integer).Value + convertedN.(Integer).Value}
	case RATIONAL_TYPE:
		r1 := convertedI.(Rational)
		r2 := convertedN.(Rational)
		result := Rational{
			Numerator:   r1.Numerator*r2.Denominator + r2.Numerator*r1.Denominator,
			Denominator: r1.Denominator * r2.Denominator,
		}
		return simplifyRational(result)
	case REAL_TYPE:
		return Real{Value: convertedI.(Real).Value + convertedN.(Real).Value}
	}

	return nil
}

// RSUB implements subtraction for Integer
func (i Integer) RSUB(n RNumber) RNumber {
	convertedI, convertedN := ConvertToSameType(i, n)

	switch convertedI.Type() {
	case INTEGER_TYPE:
		return Integer{Value: convertedI.(Integer).Value - convertedN.(Integer).Value}
	case RATIONAL_TYPE:
		r1 := convertedI.(Rational)
		r2 := convertedN.(Rational)
		result := Rational{
			Numerator:   r1.Numerator*r2.Denominator - r2.Numerator*r1.Denominator,
			Denominator: r1.Denominator * r2.Denominator,
		}
		return simplifyRational(result)
	case REAL_TYPE:
		return Real{Value: convertedI.(Real).Value - convertedN.(Real).Value}
	}

	return nil
}

// RMUL implements multiplication for Integer
func (i Integer) RMUL(n RNumber) RNumber {
	convertedI, convertedN := ConvertToSameType(i, n)

	switch convertedI.Type() {
	case INTEGER_TYPE:
		return Integer{Value: convertedI.(Integer).Value * convertedN.(Integer).Value}
	case RATIONAL_TYPE:
		r1 := convertedI.(Rational)
		r2 := convertedN.(Rational)
		result := Rational{
			Numerator:   r1.Numerator * r2.Numerator,
			Denominator: r1.Denominator * r2.Denominator,
		}
		return simplifyRational(result)
	case REAL_TYPE:
		return Real{Value: convertedI.(Real).Value * convertedN.(Real).Value}
	}

	return nil
}

// RDIV implements division for Integer
func (i Integer) RDIV(n RNumber) RNumber {
	// Special handling for integer division
	if n.Type() == INTEGER_TYPE {
		nInt := n.(Integer).Value
		if nInt == 0 {
			// Division by zero returns a rational with 0 denominator
			return Rational{Numerator: i.Value, Denominator: 0}
		}

		// Check if division is exact
		if i.Value%nInt == 0 {
			return Integer{Value: i.Value / nInt}
		}

		// Otherwise return a rational
		return simplifyRational(Rational{Numerator: i.Value, Denominator: nInt})
	}

	// For other types, convert to rational and perform division
	r1 := Rational{Numerator: i.Value, Denominator: 1}
	convertedR1, convertedN := ConvertToSameType(r1, n)

	rational1 := convertedR1.(Rational)

	switch convertedN.Type() {
	case RATIONAL_TYPE:
		r2 := convertedN.(Rational)
		result := Rational{
			Numerator:   rational1.Numerator * r2.Denominator,
			Denominator: rational1.Denominator * r2.Numerator,
		}
		return simplifyRational(result)
	case REAL_TYPE:
		r2 := convertedN.(Real)
		return Real{Value: float64(rational1.Numerator) / float64(rational1.Denominator) / r2.Value}
	}

	return nil
}

// RADD implements addition for Rational
func (r Rational) RADD(n RNumber) RNumber {
	// Check what type n is and handle appropriately
	switch n.Type() {
	case INTEGER_TYPE:
		// Rational + Integer
		intN := n.(Integer)
		// Convert integer to rational and add
		intAsRat := Rational{Numerator: intN.Value, Denominator: 1}
		result := Rational{
			Numerator:   r.Numerator*intAsRat.Denominator + intAsRat.Numerator*r.Denominator,
			Denominator: r.Denominator * intAsRat.Denominator,
		}
		return simplifyRational(result)

	case RATIONAL_TYPE:
		// Rational + Rational
		ratN := n.(Rational)
		result := Rational{
			Numerator:   r.Numerator*ratN.Denominator + ratN.Numerator*r.Denominator,
			Denominator: r.Denominator * ratN.Denominator,
		}
		return simplifyRational(result)

	case REAL_TYPE:
		// Rational + Real
		realN := n.(Real)
		ratValue := float64(r.Numerator) / float64(r.Denominator)
		return Real{Value: ratValue + realN.Value}
	}

	return nil
}

// RSUB implements subtraction for Rational
func (r Rational) RSUB(n RNumber) RNumber {
	convertedR, convertedN := ConvertToSameType(r, n)

	switch convertedN.Type() {
	case RATIONAL_TYPE:
		r1 := convertedR.(Rational)
		r2 := convertedN.(Rational)
		result := Rational{
			Numerator:   r1.Numerator*r2.Denominator - r2.Numerator*r1.Denominator,
			Denominator: r1.Denominator * r2.Denominator,
		}
		return simplifyRational(result)
	case REAL_TYPE:
		r1 := convertedR.(Real)
		r2 := convertedN.(Real)
		return Real{Value: r1.Value - r2.Value}
	}

	return nil
}

// RMUL implements multiplication for Rational
func (r Rational) RMUL(n RNumber) RNumber {
	convertedR, convertedN := ConvertToSameType(r, n)

	switch convertedN.Type() {
	case RATIONAL_TYPE:
		r1 := convertedR.(Rational)
		r2 := convertedN.(Rational)
		result := Rational{
			Numerator:   r1.Numerator * r2.Numerator,
			Denominator: r1.Denominator * r2.Denominator,
		}
		return simplifyRational(result)
	case REAL_TYPE:
		r1 := convertedR.(Real)
		r2 := convertedN.(Real)
		return Real{Value: r1.Value * r2.Value}
	}

	return nil
}

// RDIV implements division for Rational
func (r Rational) RDIV(n RNumber) RNumber {
	convertedR, convertedN := ConvertToSameType(r, n)

	switch convertedN.Type() {
	case RATIONAL_TYPE:
		r1 := convertedR.(Rational)
		r2 := convertedN.(Rational)
		if r2.Numerator == 0 {
			return Rational{Numerator: r1.Numerator * r2.Denominator, Denominator: 0}
		}
		result := Rational{
			Numerator:   r1.Numerator * r2.Denominator,
			Denominator: r1.Denominator * r2.Numerator,
		}
		return simplifyRational(result)
	case REAL_TYPE:
		r1 := convertedR.(Rational)
		r2 := convertedN.(Real)
		if r2.Value == 0 {
			return Real{Value: math.Inf(1)} // Positive infinity
		}
		val1 := float64(r1.Numerator) / float64(r1.Denominator)
		return Real{Value: val1 / r2.Value}
	}

	return nil
}

// RADD implements addition for Real
func (re Real) RADD(n RNumber) RNumber {
	convertedRe, convertedN := ConvertToSameType(re, n)

	r1 := convertedRe.(Real)
	switch convertedN.Type() {
	case REAL_TYPE:
		r2 := convertedN.(Real)
		return Real{Value: r1.Value + r2.Value}
	}

	return nil
}

// RSUB implements subtraction for Real
func (re Real) RSUB(n RNumber) RNumber {
	convertedRe, convertedN := ConvertToSameType(re, n)

	r1 := convertedRe.(Real)
	switch convertedN.Type() {
	case REAL_TYPE:
		r2 := convertedN.(Real)
		return Real{Value: r1.Value - r2.Value}
	}

	return nil
}

// RMUL implements multiplication for Real
func (re Real) RMUL(n RNumber) RNumber {
	convertedRe, convertedN := ConvertToSameType(re, n)

	r1 := convertedRe.(Real)
	switch convertedN.Type() {
	case REAL_TYPE:
		r2 := convertedN.(Real)
		return Real{Value: r1.Value * r2.Value}
	}

	return nil
}

// RDIV implements division for Real
func (re Real) RDIV(n RNumber) RNumber {
	convertedRe, convertedN := ConvertToSameType(re, n)

	r1 := convertedRe.(Real)
	switch convertedN.Type() {
	case REAL_TYPE:
		r2 := convertedN.(Real)
		if r2.Value == 0 {
			if r1.Value > 0 {
				return Real{Value: math.Inf(1)} // Positive infinity
			} else if r1.Value < 0 {
				return Real{Value: math.Inf(-1)} // Negative infinity
			} else {
				return Real{Value: math.NaN()} // NaN
			}
		}
		return Real{Value: r1.Value / r2.Value}
	}

	return nil
}

// ADD implements addition for Complex
func (c Complex) ADD(cn Number) Number {
	// If adding with a non-complex number, treat as complex with 0 imaginary part
	if cn.Type() != COMPLEX_TYPE {
		var num RNumber
		switch cn.Type() {
		case INTEGER_TYPE:
			num = cn.(Integer)
		case RATIONAL_TYPE:
			num = cn.(Rational)
		case REAL_TYPE:
			num = cn.(Real)
		}
		cn = Complex{RealPart: num, ImagPart: Integer{Value: 0}}
	}

	c2 := cn.(Complex)

	newReal := c.RealPart.RADD(c2.RealPart)
	newImaginary := c.ImagPart.RADD(c2.ImagPart)

	// Check if imaginary part is zero (for any type)
	imagIsZero := false
	switch newImaginary.Type() {
	case INTEGER_TYPE:
		if newImaginary.(Integer).Value == 0 {
			imagIsZero = true
		}
	case REAL_TYPE:
		if newImaginary.(Real).Value == 0.0 {
			imagIsZero = true
		}
	}

	// If imaginary part is 0, return just the real part
	if imagIsZero {
		switch newReal.Type() {
		case INTEGER_TYPE:
			return newReal.(Integer)
		case RATIONAL_TYPE:
			return newReal.(Rational)
		case REAL_TYPE:
			return newReal.(Real)
		}
	}

	return Complex{RealPart: newReal, ImagPart: newImaginary}
}

// SUB implements subtraction for Complex
func (c Complex) SUB(cn Number) Number {
	// If subtracting with a non-complex number, treat as complex with 0 imaginary part
	if cn.Type() != COMPLEX_TYPE {
		var num RNumber
		switch cn.Type() {
		case INTEGER_TYPE:
			num = cn.(Integer)
		case RATIONAL_TYPE:
			num = cn.(Rational)
		case REAL_TYPE:
			num = cn.(Real)
		}
		cn = Complex{RealPart: num, ImagPart: Integer{Value: 0}}
	}

	c2 := cn.(Complex)

	newReal := c.RealPart.RSUB(c2.RealPart)
	newImaginary := c.ImagPart.RSUB(c2.ImagPart)

	// Check if imaginary part is zero (for any type)
	imagIsZero := false
	switch newImaginary.Type() {
	case INTEGER_TYPE:
		if newImaginary.(Integer).Value == 0 {
			imagIsZero = true
		}
	case REAL_TYPE:
		if newImaginary.(Real).Value == 0.0 {
			imagIsZero = true
		}
	}

	// If imaginary part is 0, return just the real part
	if imagIsZero {
		switch newReal.Type() {
		case INTEGER_TYPE:
			return newReal.(Integer)
		case RATIONAL_TYPE:
			return newReal.(Rational)
		case REAL_TYPE:
			return newReal.(Real)
		}
	}

	return Complex{RealPart: newReal, ImagPart: newImaginary}
}

// MUL implements multiplication for Complex
func (c Complex) MUL(cn Number) Number {
	// If multiplying with a non-complex number, treat as complex with 0 imaginary part
	if cn.Type() != COMPLEX_TYPE {
		var num RNumber
		switch cn.Type() {
		case INTEGER_TYPE:
			num = cn.(Integer)
		case RATIONAL_TYPE:
			num = cn.(Rational)
		case REAL_TYPE:
			num = cn.(Real)
		}
		cn = Complex{RealPart: num, ImagPart: Integer{Value: 0}}
	}

	c2 := cn.(Complex)

	// (a + bi) * (c + di) = (ac - bd) + (ad + bc)i
	newReal := c.RealPart.RMUL(c2.RealPart).RSUB(c.ImagPart.RMUL(c2.ImagPart))
	newImaginary := c.RealPart.RMUL(c2.ImagPart).RADD(c.ImagPart.RMUL(c2.RealPart))

	// Check if imaginary part is zero (for any type)
	imagIsZero := false
	switch newImaginary.Type() {
	case INTEGER_TYPE:
		if newImaginary.(Integer).Value == 0 {
			imagIsZero = true
		}
	case REAL_TYPE:
		if newImaginary.(Real).Value == 0.0 {
			imagIsZero = true
		}
	}

	// If imaginary part is 0, return just the real part
	if imagIsZero {
		switch newReal.Type() {
		case INTEGER_TYPE:
			return newReal.(Integer)
		case RATIONAL_TYPE:
			return newReal.(Rational)
		case REAL_TYPE:
			return newReal.(Real)
		}
	}

	return Complex{RealPart: newReal, ImagPart: newImaginary}
}

// DIV implements division for Complex
func (c Complex) DIV(cn Number) Number {
	// If dividing by a non-complex number, treat as complex with 0 imaginary part
	if cn.Type() != COMPLEX_TYPE {
		var num RNumber
		switch cn.Type() {
		case INTEGER_TYPE:
			num = cn.(Integer)
		case RATIONAL_TYPE:
			num = cn.(Rational)
		case REAL_TYPE:
			num = cn.(Real)
		}
		cn = Complex{RealPart: num, ImagPart: Integer{Value: 0}}
	}

	c2 := cn.(Complex)

	// Check for division by zero
	if c2.RealPart.Type() == INTEGER_TYPE && c2.RealPart.(Integer).Value == 0 &&
		c2.ImagPart.Type() == INTEGER_TYPE && c2.ImagPart.(Integer).Value == 0 {
		return Complex{
			RealPart: Real{Value: math.Inf(1)},
			ImagPart: Real{Value: math.Inf(1)},
		}
	}

	// (a + bi) / (c + di) = ((a + bi) * (c - di)) / (c² + d²)
	conjugate := Complex{
		RealPart: c2.RealPart,
		ImagPart: Integer{Value: -1}.RMUL(c2.ImagPart),
	}

	numerator := c.MUL(conjugate)
	denominatorReal := c2.RealPart.RMUL(c2.RealPart).RADD(c2.ImagPart.RMUL(c2.ImagPart))

	if denominatorReal.Type() == INTEGER_TYPE && denominatorReal.(Integer).Value == 0 {
		return Complex{
			RealPart: Real{Value: math.Inf(1)},
			ImagPart: Real{Value: math.Inf(1)},
		}
	}

	var result Number
	switch numerator := numerator.(type) {
	case Complex:
		n := numerator
		newReal := n.RealPart.RDIV(denominatorReal)
		newImaginary := n.ImagPart.RDIV(denominatorReal)
		result = Complex{RealPart: newReal, ImagPart: newImaginary}
	default:
		// Numerator is a real number
		var num RNumber
		switch numerator.Type() {
		case INTEGER_TYPE:
			num = numerator.(Integer)
		case RATIONAL_TYPE:
			num = numerator.(Rational)
		case REAL_TYPE:
			num = numerator.(Real)
		}
		result = Complex{
			RealPart: num.RDIV(denominatorReal),
			ImagPart: Integer{Value: 0},
		}
	}

	// Simplify if imaginary part is 0
	if result.Type() == COMPLEX_TYPE {
		r := result.(Complex)

		// Check if imaginary part is zero (for any type)
		imagIsZero := false
		switch r.ImagPart.Type() {
		case INTEGER_TYPE:
			if r.ImagPart.(Integer).Value == 0 {
				imagIsZero = true
			}
		case REAL_TYPE:
			if r.ImagPart.(Real).Value == 0.0 {
				imagIsZero = true
			}
		}

		if imagIsZero {
			// Check if either operand contains real numbers
			c1HasReal := false
			c2HasReal := false

			// Check first operand
			if c.RealPart.Type() == REAL_TYPE || c.ImagPart.Type() == REAL_TYPE {
				c1HasReal = true
			}

			// Check second operand
			if c2.RealPart.Type() == REAL_TYPE || c2.ImagPart.Type() == REAL_TYPE {
				c2HasReal = true
			}

			// If either operand contains real numbers, return real number results
			if c1HasReal || c2HasReal {
				// Check if real part is one
				isOneValue := false
				switch r.RealPart.Type() {
				case INTEGER_TYPE:
					if r.RealPart.(Integer).Value == 1 {
						isOneValue = true
					}
				case RATIONAL_TYPE:
					rat := r.RealPart.(Rational)
					if rat.Numerator == rat.Denominator && rat.Numerator != 0 {
						isOneValue = true
					}
				case REAL_TYPE:
					if r.RealPart.(Real).Value == 1.0 {
						isOneValue = true
					}
				}

				if isOneValue {
					return Real{Value: 1.0}
				}

				// Check if real part is zero
				isZero := false
				switch r.RealPart.Type() {
				case INTEGER_TYPE:
					if r.RealPart.(Integer).Value == 0 {
						isZero = true
					}
				case REAL_TYPE:
					if r.RealPart.(Real).Value == 0.0 {
						isZero = true
					}
				}

				if isZero {
					return Real{Value: 0.0}
				}
			} else {
				// Both operands are exact, can return exact results
				if isOne(r.RealPart) {
					return Integer{Value: 1}
				}
			}
			return convertToNumber(r.RealPart)
		}
	}

	return result
}

func (x Integer) RNEG() RNumber {
	return Integer{Value: -x.Value}
}

func (x Integer) NEG() Number {
	return Integer{Value: -x.Value}
}

func (x Rational) NEG() Number {
	return Rational{
		Numerator:   -x.Numerator,
		Denominator: -x.Denominator,
	}
}

func (x Rational) RNEG() RNumber {
	return Rational{
		Numerator:   -x.Numerator,
		Denominator: -x.Denominator,
	}
}
func (x Real) NEG() Number {
	return Real{Value: -x.Value}
}

func (x Real) RNEG() RNumber {
	return Real{Value: -x.Value}
}
func (x Complex) NEG() Number {
	return Complex{
		RealPart: x.RealPart.RNEG(),
		ImagPart: x.ImagPart.RNEG(),
	}
}

func NewRational(numerator, denominator int64) Number {
	r := Rational{
		Numerator:   numerator,
		Denominator: denominator,
	}
	s := simplifyRational(r)
	return convertToNumber(s)
}

func RNumber_CMP(a, b RNumber) int {
	var ra big.Rat
	switch a.Type() {
	case INTEGER_TYPE:
		ra.SetInt64(a.(Integer).Value)
	case RATIONAL_TYPE:
		ra.SetFrac64(a.(Rational).Numerator, a.(Rational).Denominator)
	case REAL_TYPE:
		ra.SetFloat64(a.(Real).Value)
	}
	var rb big.Rat
	switch b.Type() {
	case INTEGER_TYPE:
		rb.SetInt64(b.(Integer).Value)
	case RATIONAL_TYPE:
		rb.SetFrac64(b.(Rational).Numerator, b.(Rational).Denominator)
	case REAL_TYPE:
		rb.SetFloat64(b.(Real).Value)
	}
	return ra.Cmp(&rb)
}

func Complex_Equal(a, b Complex) bool {
	return RNumber_CMP(a.RealPart, b.RealPart) == 0 && RNumber_CMP(a.ImagPart, b.ImagPart) == 0
}

// bigIntToFloat64 converts a big.Int to float64 using big.Float as intermediate.
func bigIntToFloat64(b *big.Int) float64 {
	bf := new(big.Float).SetInt(b)
	f, _ := bf.Float64()
	return f
}

type BigInteger big.Int

func (bi BigInteger) Type() NumberType {
	return BIG_INTEGER_TYPE
}

func (bi BigInteger) String() string {
	bigInt := big.Int(bi)
	return bigInt.String()
}

// Additional methods for BigInteger can be implemented as needed

func NewBigIntegerFromString(s string) (BigInteger, error) {
	var bigInt big.Int
	_, ok := bigInt.SetString(s, 10)
	if !ok {
		return BigInteger{}, fmt.Errorf("invalid big integer string: %s", s)
	}
	return BigInteger(bigInt), nil
}

func (bi BigInteger) RADD(n RNumber) RNumber {
	a := big.Int(bi)
	switch n.Type() {
	case BIG_INTEGER_TYPE:
		b := big.Int(n.(BigInteger))
		var res big.Int
		res.Add(&a, &b)
		return BigInteger(res)
	case INTEGER_TYPE:
		b := big.NewInt(n.(Integer).Value)
		var res big.Int
		res.Add(&a, b)
		return BigInteger(res)
	case RATIONAL_TYPE:
		// fall back to Real
		af := bigIntToFloat64(&a)
		r := n.(Rational)
		val := af + float64(r.Numerator)/float64(r.Denominator)
		return Real{Value: val}
	case REAL_TYPE:
		af := bigIntToFloat64(&a)
		val := af + n.(Real).Value
		return Real{Value: val}
	default:
		return nil
	}
}

func (bi BigInteger) RSUB(n RNumber) RNumber {
	a := big.Int(bi)
	switch n.Type() {
	case BIG_INTEGER_TYPE:
		b := big.Int(n.(BigInteger))
		var res big.Int
		res.Sub(&a, &b)
		return BigInteger(res)
	case INTEGER_TYPE:
		b := big.NewInt(n.(Integer).Value)
		var res big.Int
		res.Sub(&a, b)
		return BigInteger(res)
	case RATIONAL_TYPE:
		af := bigIntToFloat64(&a)
		r := n.(Rational)
		val := af - float64(r.Numerator)/float64(r.Denominator)
		return Real{Value: val}
	case REAL_TYPE:
		af := bigIntToFloat64(&a)
		val := af - n.(Real).Value
		return Real{Value: val}
	default:
		return nil
	}
}

func (bi BigInteger) RMUL(n RNumber) RNumber {
	a := big.Int(bi)
	switch n.Type() {
	case BIG_INTEGER_TYPE:
		b := big.Int(n.(BigInteger))
		var res big.Int
		res.Mul(&a, &b)
		return BigInteger(res)
	case INTEGER_TYPE:
		b := big.NewInt(n.(Integer).Value)
		var res big.Int
		res.Mul(&a, b)
		return BigInteger(res)
	case RATIONAL_TYPE:
		af := bigIntToFloat64(&a)
		r := n.(Rational)
		val := af * (float64(r.Numerator) / float64(r.Denominator))
		return Real{Value: val}
	case REAL_TYPE:
		af := bigIntToFloat64(&a)
		val := af * n.(Real).Value
		return Real{Value: val}
	default:
		return nil
	}
}

func (bi BigInteger) RDIV(n RNumber) RNumber {
	a := big.Int(bi)
	switch n.Type() {
	case BIG_INTEGER_TYPE:
		b := big.Int(n.(BigInteger))
		if b.Cmp(big.NewInt(0)) == 0 {
			return Rational{Numerator: 1, Denominator: 0}
		}
		var q, r big.Int
		q.QuoRem(&a, &b, &r)
		if r.Cmp(big.NewInt(0)) == 0 {
			return BigInteger(q)
		}
		// fall back to Real
		af := bigIntToFloat64(&a)
		bf := bigIntToFloat64(&b)
		return Real{Value: af / bf}
	case INTEGER_TYPE:
		b := big.NewInt(n.(Integer).Value)
		if b.Cmp(big.NewInt(0)) == 0 {
			return Rational{Numerator: 1, Denominator: 0}
		}
		var q, r big.Int
		q.QuoRem(&a, b, &r)
		if r.Cmp(big.NewInt(0)) == 0 {
			return BigInteger(q)
		}
		af := bigIntToFloat64(&a)
		bf := float64(n.(Integer).Value)
		return Real{Value: af / bf}
	case RATIONAL_TYPE:
		af := bigIntToFloat64(&a)
		r := n.(Rational)
		if r.Denominator == 0 {
			return Rational{Numerator: 1, Denominator: 0}
		}
		val := af / (float64(r.Numerator) / float64(r.Denominator))
		return Real{Value: val}
	case REAL_TYPE:
		if n.(Real).Value == 0.0 {
			return Real{Value: math.Inf(1)}
		}
		af := bigIntToFloat64(&a)
		val := af / n.(Real).Value
		return Real{Value: val}
	default:
		return nil
	}
}

func (bi BigInteger) RNEG() RNumber {
	bigInt := big.Int(bi)
	bigInt.Neg(&bigInt)
	return BigInteger(bigInt)
}

func (bi BigInteger) ADD(n Number) Number {
	// Treat BigInteger as a real-part complex number and delegate to Complex.ADD
	return Complex{RealPart: bi, ImagPart: Integer{Value: 0}}.ADD(n)
}

func (bi BigInteger) SUB(n Number) Number {
	return Complex{RealPart: bi, ImagPart: Integer{Value: 0}}.SUB(n)
}

func (bi BigInteger) MUL(n Number) Number {
	return Complex{RealPart: bi, ImagPart: Integer{Value: 0}}.MUL(n)
}

func (bi BigInteger) DIV(n Number) Number {
	return Complex{RealPart: bi, ImagPart: Integer{Value: 0}}.DIV(n)
}

func (bi BigInteger) NEG() Number {
	bigInt := big.Int(bi)
	bigInt.Neg(&bigInt)
	return BigInteger(bigInt)
}
*/
